<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <script>
        var name = '栓';
        var quan = {
            name: '铨'
        };
        function sayName(obj) {
            console.log(this.name)
            console.log(obj)
            console.log(arguments)
        }

        // 比较好理解的
        // Function.prototype.myBind = function (context) {
        //     if (typeof this !== 'function') {
        //         throw new TypeError('not function')
        //     }
        //     let _this = this
        //     console.log(arguments)
        //     // 自己的理解是，因为用了闭包这里得先接受他一遍参数
        //     let args = [...arguments].slice(1)
        //     // 处理函数使用new的情况
        //     return function F() {
        //         if (this instanceof F) {
        //             return new _this(...args, ...arguments)
        //         } else {
        //             return _this.apply(context, args.concat(...arguments))
        //         }
        //     }
        // }

        // 简化方法--2022-12-03
        Function.prototype.myBind = function (context,...args) {
            if (typeof this !== 'function') {
                throw new TypeError('not function')
            }
            let _this = this
            console.log(args)
            // 处理函数使用new的情况
            return function F(...args2) {
                // 2024-01-08
                // if (new.target) {
                if (this instanceof F) {
                    return new _this(...args, ...args2)
                } else {
                    // call和apply的arguments的数据结构不一样
                    // return _this.apply(context, args.concat(...args2))
                    return _this.apply(context, [...args,...args2])
                    // return _this.call(context, args,args2)
                }
            }
        }

        // 简化版(自己写的)(处理不了new的情况)
        // Function.prototype.myBind = function (context) {
        //     let _this = this
        //     let args = [...arguments].slice(1)
        //     return function F() {
        //         return _this.apply(context, args)
        //     }
        // }

        // 简化方法(处理不了new的情况)--2022-12-03
        Function.prototype.myBind2 = function (context, ...args) {
            if (typeof this !== 'function') {
                throw new TypeError('not function')
            }
            return (...args2)=>{
                console.log(this)
                console.log(context)
                console.log(args)
                console.log(args2)
                return this.apply(context, [...args,...args2])
            }
        }

        sayName()
        let _ = sayName.myBind(quan, 'tt','tt2')
        _('tt3')
        // 采用new
        // let _ = sayName.myBind(quan)
        // new _('tt3')
        let vv = sayName.myBind2(quan, 'tt','tt2')
        vv('tt3')
    </script>
</body>

</html>